-- This design takes the inputs from various keyboard keys and outputs it to various signals

-- library IEEE, unisim;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
--use unisim.vcomponents.all;
--use work.ps2_kbd_pckg.all;


entity ps2 is
  generic(
    FREQ			:     natural := 100_000    -- frequency of main clock (KHz)
    );
  port(
    clk      	: in  std_logic;           -- main clock
    ps2_clk  	: in  std_logic;           -- keyboard clock
    ps2_data 	: in  std_logic;           -- keyboard data
	 keyrel_out	: out	std_logic;
	 keyboardOut	: out std_logic_vector(9 downto 0)
    );
end entity;


architecture arch of ps2 is

	component keycontrol
  		generic(
    		FREQ     :     natural := 100_000   -- frequency of the main clock (KHz)
    	);
  		port(
    		clk      : in  std_logic;           -- main clock
    		rst      : in  std_logic;           -- asynchronous reset
    		ps2_clk  : in  std_logic;           -- clock from keyboard
    		ps2_data : in  std_logic;           -- data from keyboard
    		scancode : out std_logic_vector(7 downto 0);  -- key scancode
    		parity   : out std_logic;           -- parity bit for scancode
    		busy     : out std_logic;           -- busy receiving scancode
    		rdy      : out std_logic;           -- scancode ready pulse
    		error    : out std_logic            -- error receiving scancode
    	);
   end component;

  constant YES		: std_logic := '1';
  constant NO  		: std_logic := '0';

  signal scancode  	: std_logic_vector(7 downto 0);  -- scancode from keyboard
  signal rdy       	: std_logic;         -- indicates when scancode is available
  signal s_x       	: std_logic_vector(6 downto 0);  -- next state of LED segments
  signal kbd_error	: std_logic;         -- error receiving scancode from keyboard
  signal keyrel	   : std_logic;
  signal rst : std_logic;
  signal keyboard		: std_logic_vector(9 downto 0);

  -- LED segment activation patterns for various numbers and letters
  constant DIG_1    : std_logic_vector(0 to 6) := "0100100";
  constant DIG_2    : std_logic_vector(0 to 6) := "1011101";
  constant DIG_3    : std_logic_vector(0 to 6) := "1101101";
  constant DIG_4    : std_logic_vector(0 to 6) := "0101110";
  constant DIG_5    : std_logic_vector(0 to 6) := "1101011";
  constant DIG_6    : std_logic_vector(0 to 6) := "1111011";
  constant DIG_7    : std_logic_vector(0 to 6) := "0100101";
  constant DIG_8    : std_logic_vector(0 to 6) := "1111111";
  constant DIG_9    : std_logic_vector(0 to 6) := "1101111";
  constant DIG_0    : std_logic_vector(0 to 6) := "1110111";
  constant LETTER_E : std_logic_vector(0 to 6) := "1011011";

begin
     rst <=  not kbd_error;
  u0 : keycontrol
    generic map(
      FREQ     		=> FREQ
      )
    port map(
      clk      		=> clk,                  -- clock for the keyboard interface
      rst      		=> rst,            -- reset the keyboard intfc whenever there is an error receiving a scancode
      ps2_clk  		=> ps2_clk,              -- clock from the keyboard
      ps2_data 		=> ps2_data,             -- serial data from the keyboard (valid on falling edge of ps2_clk)
      scancode 		=> scancode,             -- the scancode received from the keyboard
      rdy      		=> rdy,                  -- indicates when a scancode from the keyboard is available
      error    		=> kbd_error            -- indicates an error in receiving a scancode from the keyboard
      );
	
	-- map the signals from the buttons to the outputs
	keyboardOut <= keyboard;
	
	-- update up and down buttons
	process(clk)
	begin
		if (rising_edge(clk) and rdy = YES) then
			-- W, S, A, D, UP, DOWN, LEFT, RIGHT, SPACE, ALT
			-- UP1, DOWN1, LEFT1, RIGHT1, UP2, DOWN2, LEFT2, RIGHT2, START, DEBUG
			case scancode is
				when "11110000" => -- key released scancode
					keyrel <= '1';
				when "00011101" => --key "w"	player1 up
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(9) <= '0';
					else
						keyboard(9) <= '1';
					end if;
				when "00011011" => --key "s" player1 down		
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(8) <= '0';
					else
						keyboard(8) <= '1';
					end if;
				when "00011100" => --key "a" player1 left
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(7) <= '0';
					else
						keyboard(7) <= '1';
					end if;
				when "00100011" => --key "d"	player1 right
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(6) <= '0';
					else
						keyboard(6) <= '1';
					end if;
				when "01110101" => --key "uparrow" player2 up
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(5) <= '0';
					else
						keyboard(5) <= '1';
					end if;
				when "01110010" => --key "downarrow" player2 down
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(4) <= '0';
					else
						keyboard(4) <= '1';
					end if;
				when "01101011" => --key "leftarrow" player2 left
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(3) <= '0';
					else
						keyboard(3) <= '1';
					end if;
				when "01110100" => --key "rightarrow"	player2 right
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(2) <= '0';
					else
						keyboard(2) <= '1';
					end if;
				when "00101001" => --key "space" start
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(1) <= '0';
					else
						keyboard(1) <= '1';
					end if;
				when "00010001" => --key "alt" debug
					keyrel <= '0';
					if (keyrel = '1') then
						keyboard(0) <= '0';
					else
						keyboard(0) <= '1';
					end if;
				when others =>
					null;
			end case;
		end if;
	end process;
end architecture;
